import os
import codecs
from openpyxl import load_workbook
from openpyxl.worksheet.table import Table
from openpyxl.styles import Alignment
from enum import Enum, auto
from datetime import datetime  

# 定义结构体
class Controller(Enum):
    CanController_CAN0 = 0          # BCAN
    CanController_CAN1 = auto()     # CCAN
    CanController_CAN2 = auto()     # PCAN
    CanController_CAN3 = auto()     # ADBCANFD
    CanController_CAN4 = auto()     # OBDCAN
    CanController_CAN5 = auto()
# class Controller(Enum):
#     CanController_CAN0 = 2          # BCAN
#     CanController_CAN1 = 1     # CCAN
#     CanController_CAN2 = 0     # PCAN
#     CanController_CAN3 = 3     # ADBCANFD
#     CanController_CAN4 = 4     # OBDCAN

class attr_t:
    def __init__(self, cycle):
        self.cycle = cycle

class can_frame_route_t:
    def __init__(self, id, src_bus, attribute, dst_bus):
        self.id = id
        self.src_bus = src_bus
        self.attribute = attribute
        self.dst_bus = dst_bus

# 读取 Excel 文件基本信息
wb = load_workbook(filename='routing_table.xlsx', read_only=True)
active_sheet = wb.active
# print(type(active_sheet))
# print(wb.sheetnames)

# 读取路由表名称
ws = wb["Cover"]
routing_table_name = ws['B6'].value
# 如果单元格有内容，则去除换行符，整合成一行
# 检查单元格是否有富文本
if hasattr(routing_table_name, 'rich_text') and routing_table_name.rich_text:
    # 遍历富文本中的所有段落
    for i, paragraph in enumerate(routing_table_name.rich_text.paragraphs):
        # 删除换行符并设置新的文本
        routing_table_name.rich_text.paragraphs[i].text = paragraph.text.replace('\n', ' ')
else:
    # 如果单元格没有富文本，直接设置文本
    routing_table_name = routing_table_name.replace('\n', ' ')

print(routing_table_name)

# 读取版本等信息
ws = wb["History"]
for row in ws.iter_rows(min_row=3, values_only=True):
    if row[0] == None:
        break
    routing_table_rev = row[0]
    routing_table_date = row[1]
    routing_table_author = row[2]
    routing_table_change_comment = row[6]
print(routing_table_rev, routing_table_date, routing_table_author, routing_table_change_comment)

# 读取 Excel 文件中的指定表格
ws = wb["MessageRoutingTable"]
print(ws.title)

routing_table = []
routing_table_len = 0
src_bus = Controller.CanController_CAN2.value
dst_bus = Controller.CanController_CAN1.value
for row in ws.iter_rows(min_row=1, values_only=True):
    # 解析数据源
    if row[0] == "requested signals, source:PCAN":
        src_bus = Controller.CanController_CAN2.value
    elif row[0] == "requested signals, source:CCAN":
        src_bus = Controller.CanController_CAN1.value
    elif row[0] == "requested signals, source:BCAN":
        src_bus = Controller.CanController_CAN0.value
    elif row[0] == "requested signals, source:ACAN":
        src_bus = Controller.CanController_CAN3.value
    elif row[0] == "requested signals, source:OBD":
        src_bus = Controller.CanController_CAN4.value
    
    # 解析数据目标
    if row[3] == "distributed messages, target:CCAN":
        dst_bus = Controller.CanController_CAN1.value
        continue
    elif row[3] == "distributed messages, target:BCAN":
        dst_bus = Controller.CanController_CAN0.value
        continue
    elif row[3] == "distributed messages, target:ACAN":
        dst_bus = Controller.CanController_CAN3.value
        continue
    elif row[3] == "distributed messages, target:OBD":
        dst_bus = Controller.CanController_CAN4.value
        continue
    elif row[3] == "distributed messages, target:PCAN":
        dst_bus = Controller.CanController_CAN2.value
        continue

    # 解析 Message ID
    try:
        row_2_2 = row[2][:2]
    except TypeError as e:
        print(e)
        print(row)
        continue
    if row_2_2 == "0x":
        if row[2] != row[5]:    # execl中存在不一致情况，按源ID走
            print("Message ID 不一致")
            print(row)
            # continue
        # 去掉头部的 “0x” 和 尾部的 “x”
        smid = row[2].lstrip("0x").rstrip('x')

        # 转换成十六为整数
        id = int(smid, 16)
        
        attribute = attr_t(cycle=0)
        route = can_frame_route_t(id=id, src_bus=src_bus, attribute=attribute, dst_bus=dst_bus)
        routing_table.append(route)
        routing_table_len += 1

# 输出结果
print("总共有", routing_table_len, "条路由信息")

# 获取当前时间用于生成说明
now = datetime.now().strftime("%Y-%m-%d %H:%M:%S")

# 生成头文件
# 创建要写入文件的完整文本字符串
header_text = """/*
 * This file is automatically generated and does not allow modification!
 * Routing Table basic information
 * File name: {name}
 * Revision: {rev}, Date: {ddd1}
 * Change Comment: {comment}
 *
 * Author: GangSongSong
 * Date: {ddd2}
*/

#ifndef PDUR_H_
#define PDUR_H_

#include "Mcu.h"
#include "Can_GeneralTypes.h"

/*note: CAN_ROUT_LEN means the max len*/
#define CAN_ROUT_MAX_LEN    {table_len}

typedef struct
{{
    /*send cycle, 0 means send directly.*/
    uint8 cycle;
}}attr_t;

typedef struct cfr
{{
    uint32 id;
    Can_HwHandleType src_bus;
    attr_t attribute;
    Can_HwHandleType dst_bus;
}}can_frame_route_t;

typedef struct cft
{{
    uint32 len;
    can_frame_route_t can_frame_route;
}}can_frame_table_t;

extern volatile const uint32 PDUR_LEN;
extern volatile const can_frame_route_t pdur_table[CAN_ROUT_MAX_LEN];

#endif /* PDUR_H_ */
"""
header_text_f = header_text.format(
    name = routing_table_name,
    rev = routing_table_rev,
    ddd1 = routing_table_date,
    # author = routing_table_author,
    comment = routing_table_change_comment,
    ddd2 = now,
    table_len = routing_table_len
)

h_file_path = os.path.join(".", 'pdur.h')
with codecs.open(h_file_path, 'w', 'gbk') as h_file:
    h_file.write(header_text_f)

print(f'Header file have been generated in {h_file_path}')

source_text_front = """/*
 * This file is automatically generated and does not allow modification!
 * Routing Table basic information
 * File name: {name}
 * Revision: {rev}, Date: {ddd1}
 * Change Comment: {comment}
 *
 * Author: GangSongSong
 * Date: {ddd2}
*/
#ifdef __cplusplus
extern "C" {{
#endif

#include "pdur.h"

__attribute__ ((section (".pdur_rom_section")))volatile const uint32 PDUR_LEN = CAN_ROUT_MAX_LEN;
__attribute__ ((section (".pdur_rom_section")))volatile const can_frame_route_t pdur_table[CAN_ROUT_MAX_LEN] =
{{
"""

source_text_front_f = source_text_front.format(
    name = routing_table_name,
    rev = routing_table_rev,
    ddd1 = routing_table_date,
    # author = routing_table_author,
    comment = routing_table_change_comment,
    ddd2 = now,
)

source_text_back = """};

#ifdef __cplusplus
}
#endif
"""

# 生成C文件
c_file_path = os.path.join(".", 'pdur.c')  
with codecs.open(c_file_path, 'w', 'gbk') as c_file:  
    c_file.write(source_text_front_f)  
    # 这里你可以根据Excel中的数据生成C代码逻辑  
    # 例如，假设Excel中第一列包含变量名，第二列包含变量值  
    for route in routing_table:
        # print(f"id: {route.id}, src_bus: {route.src_bus}, attribute.cycle: {route.attribute.cycle}, dst_bus: {route.dst_bus}")
        c_file.write(f'\t{{ 0x{route.id:02X}, {route.src_bus}, {{ {route.attribute.cycle} }}, {route.dst_bus} }},\n')
    c_file.write(source_text_back)
print(f'C file have been generated in {c_file_path}')